iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0

Table of Contents

  • 一些Document屬性指定的元素
  • querySelector系列
    • querySelector()
      • document.querySelector()
      • element.querySelector()
    • querySelectorAll()
      • document.querySelectorAll()
      • element.querySelectorAll()
  • getElement系列
    • Document: getElementById()
    • Document.getElementsByClassName()
    • Document: getElementsByTagName()
    • Document: getElementsByName()
  • static?live?nodelist與HTMLCollection
    • Nodelist
    • HTMLCollection
    • static Nodelist
  • References

一些Document屬性指定的元素

Document本身有提供一些方法可以存取節點,例如:Document.bodyDocument.head,會各自回傳<body><head>內容,比方說使用document.body.style.backgroundColor = "yellow"; 會更改背景的顏色。

querySelector系列

Selectors API提供querySelector比對選擇器,去搜尋DOM中的節點方法。querySelector分成querySelector()querySelectorAll()

querySelector()

document.querySelector()

簡單來說在DOM去搜尋節點,括號中需要有單引號或雙引號,內容照平常使用選擇器的方式來寫。看到document.querySelectorAll()的名字,就會想document.querySelector()是不是只選某個元素。但更貼近這個方法的說法是,使用這個方法會回傳文件中的第一個元素,即使符合選擇器的元素很多,也只會回傳這個序列中的第一個。

範例程式碼:

<h1>contestantNumber: 1</h1>
<ul>
    <li>hotpotFlavor: Spicy Sichuan</li>
    <li>hotpotIngredients:Beef slices, Tofu, Enoki mushrooms, Napa cabbage</li>
    <li>beveragePairing: Jasmine tea</li>
</ul>

querySelector()跟選擇程式碼中的<li>

console.log(document.querySelector('li'))

element.querySelector()

跟document不一樣的是,element可以選擇內建的document方法或者document.queryselector選到的元素。

拿上面的程式碼來示範:

//存到變數
const ul = document.querySelector('ul')
console.log(ul.querySelector('li'))

//也可以不要存變數
console.log(document.querySelector('ul').querySelector('li'))

//使用預設方法
console.log(document.body.querySelector('li'))

有趣的是當我使用codepen來嘗試這些程式碼,我沒有把這些程式碼放到body,但預設上已經把這些元素當成他的child,也可以存取到這些node。(不過我只是測試用,平常請寫完整)

querySelectorAll()

document.querySelectorAll()

當使用這個方法,可以一次選取多個節點,使用時會回傳一個靜態的nodelist。
依照剛剛的程式碼,改成document.querySelectorAll()

console.log(document.querySelectorAll('li'))

會回傳一個有序列跟長度的nodelist。

element.querySelectorAll()

用法同理先前element.querySelector(),回傳的結果也跟document.querySelectorAll()一樣回傳一個靜態的nodelist。

getElement系列

Document: getElementById()

不像querySelectorAll()會回傳一個list,在這個方法中ID是唯一的,即使有重複的ID,也只會回傳一個。

例如把每個<li>加上一個同樣的ID:

<h1>contestantNumber: 1</h1>
<ul>
    <li id='text'>hotpotFlavor: Spicy Sichuan</li>
    <li id='text'>>hotpotIngredients:Beef slices, Tofu, Enoki mushrooms, Napa cabbage</li>
    <li id='text'>    beveragePairing: Jasmine tea
    </li>
</ul>
console.log(document.getElementById('text'))


僅回傳這一個元素。

Document.getElementsByClassName()

使用class name選取,中間可以用一個空格隔開,去找完全符合這個條件的元素。

<h1>contestantNumber: 1</h1>
<ul>
    <li class='text'>hotpotFlavor: Spicy Sichuan</li>
    <li class='text'>>hotpotIngredients:Beef slices, Tofu, Enoki mushrooms, Napa cabbage</li>
    <li class='text'>    beveragePairing: Jasmine tea
    </li>
</ul>
console.log(document.getElementsByClassName('text'))

會回傳一組Collection可以使用:

修改class name,讓方法去搜尋。現在三個li都有共通的名字叫text,第一個多兩個名字為oneflavor,第二個則是two,讓我們在方法中輸入text one

<h1>contestantNumber: 1</h1>
<ul>
    <li class="text one flavor">hotpotFlavor: Spicy Sichuan</li>
    <li class="text two">hotpotIngredients:Beef slices, Tofu, Enoki mushrooms, Napa cabbage</li>
    <li class="text">beveragePairing: Jasmine tea</li>
</ul>
console.log(document.getElementsByClassName('text one'))

回傳:

Document: getElementsByTagName()

搜尋符合標籤名稱的元素,例如用剛剛的範例搜尋<li>,就會回傳像上面的HTML collection。

Document: getElementsByName()

Name則是每個元素中的屬性內容,而且這個方法會回傳一個動態的nodelist。

<h1>contestantNumber: 1</h1>
<ul>
    <li name='text'>hotpotFlavor: Spicy Sichuan</li>
    <li name='text'>>hotpotIngredients:Beef slices, Tofu, Enoki mushrooms, Napa cabbage</li>
    <li name='text'>    beveragePairing: Jasmine tea
    </li>
</ul>
console.log(document.getElementsByName('text'))

回傳結果:

static?live?Nodelist與HTMLCollection

上面講了這麽多,而且每個方法回傳的內容都不太一樣。先從NodelistHTMLCollection來說起。

Nodelist

Nodelist是Node的集合,雖然很像陣列但並不是,只能使用一些Array方法。像剛才的querySelectorAll()getElementsByName()都會回傳一組Nodelist,但前者是一個靜態(static),另一個則是動態的(live)。

差異在於如果Nodelist是靜態的,那麽透過querySelectorAll()回傳一個list之後做出對DOM的改變都是不會發生的,至於動態就會照常變更。

HTMLCollection

HTMLCollection是元素的集合,並且有兩個實例方法。如果DOM更新的時候,就會即時反應在HTMLCollection
儘管因為動態的關係讓HTMLCollection看起來很方便,但能用的方法實在不多。

static Nodelist

再一次使用剛才的範例:

<h1>contestantNumber: 1</h1>
<ul>
    <li>hotpotFlavor: Spicy Sichuan</li>
    <li>hotpotIngredients:Beef slices, Tofu, Enoki mushrooms, Napa cabbage</li>
    <li>beveragePairing: Jasmine tea
    </li>
</ul>
//在最一開始取得li的list
const li = document.querySelectorAll('li');
//取外層容器作為等等新增元素的地方
const ul = document.querySelector('ul')
//新增第四個li
const newLi = document.createElement("li");
//對新的li新增文字
newLi.innerText = `extraDish: Crispy fried wontons`;
//在ul裡面新增剛剛的li
ul.appendChild(newLi);
console.log(li)

而畫面中的確有ul元素:

但nodelist的內容始終只有最一開始的三個:

li.forEach((eachLi=>{
  eachLi.style.color="blue"
}))

這時候再對每個<li>改樣式,就會發現根本改不動第四個。

那要怎麽辦呢?如果只想用document.querySelectorAll(),就需要在更動DOM的時候再一次使用document.querySelectorAll()

const ul = document.querySelector('ul')
const newLi = document.createElement("li");
newLi.innerText = `extraDish: Crispy fried wontons`;
ul.appendChild(newLi);
//在這裡抓一次list
const li2 = document.querySelectorAll('li');
li2.forEach((eachLi=>{
  eachLi.style.color="blue"
}))

所有文字都成功變色:

至於想使用哪種方式抓取list,可以看個人需求決定。

題外話,在爬找資料時我突然對querySelectorAll()存取到的nodelist跟childNodeslist感到混亂,才想到querySelector已經是有用選擇器當作篩選條件,只選取相符合的selector,而像childNodes是去選父層下面所有的節點。

References

Live vs. static NodeLists and HTMLCollections in vanilla JS
When is NodeList live and when is it static?

  • MDN
  1. Locating DOM elements using selectors
  2. Document: querySelector() method
  3. Element: querySelector() method
  4. Document: querySelectorAll() method
  5. Element: querySelectorAll() method
  6. Document: getElementsByClassName() method
  7. Document: getElementById() method
  8. Document: getElementsByName() method
  9. Document: getElementsByTagName() method
  10. HTMLCollection
  11. NodeList

上一篇
〈Day17〉控制在DOM的元素(中)
下一篇
〈Day19〉處理DOM的CSS
系列文
廚藝不精也可以,給自己做一份Javascript小火鍋30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言